#include "tls_statem.h"
#include "tls_common.h"
#include "tls_connection.h"
#include "tls_fs.h"
#include "tls_x509.h"
#include "tls_curve.h"
#include "tls_alloc.h"
#include "tls_hmac.h"
#include "tls_sha256.h"
#include "tls_rsa.h"
#include "uECC.h"

int connected = 0;
unsigned char client_pms[32];
unsigned char server_pms[32];
unsigned char client_pubkey[1024];
unsigned char server_pubkey[1024];
int state_machine(int server) {
    static TCP_CONNECTION *conn = NULL;
    struct socket *client_sock = NULL;  
    int (*handle) (SSL_CONNECTION *s, PACKET *pkt);
    int (*transition) (SSL_CONNECTION *s);
    int (*get_handle_message_f) (SSL_CONNECTION *s,
                                 int (**confunc) (SSL_CONNECTION *s, PACKET *pkt));
    PACKET *position;
    int ret_size = 0;
    conn = alloc_connection();
    if (conn == NULL) {
        return -1;
    } else {
        position = conn->buf;
        conn->ssl->server = server;
        conn->ssl->pkt_size = 0;
    }
    if (conn->ssl->server) {
        server_init_listen(conn);
        transition = ssl_statem_server_transition;
        get_handle_message_f = ssl_statem_server_handle_message;
        int ret = 0;  

    server_accept:
        ret = kernel_accept(conn->sock, &client_sock, 64);

        if (ret < 0) {  
            printk("server:accept error!\n");  
            goto end;  
        } else {
            conn->ssl->hand_state = TLS_ST_BEFORE;
            position = conn->buf;
            conn->ssl->pkt_size = 0;
        }  

        printk("server: accept ok, Connection Established\n");  

        ret = ksock_recv(client_sock, conn->buf, BUFFER_SIZE, MSG_NOSIGNAL);
        if (ret >= BUFFER_SIZE || ret < 0) {
            goto end;
        }
        print_hex_dump(KERN_CONT, "kernel_recv_clienthello:", DUMP_PREFIX_OFFSET, 16, 1, conn->buf, ret, false);
    } else {
        client_init_connection(conn);
        conn->ssl->hand_state = TLS_ST_BEFORE;
        transition = ssl_statem_client_transition;
        get_handle_message_f = ssl_statem_client_handle_message;
    }

    while(1) {
        transition(conn->ssl);
        if (conn->ssl->hand_state == TLS_ST_OK) {
            printk("%s_current_state: %s full_state:%s\n", server == 1 ? "server": "client",
                   conn->ssl->hand_state == TLS_ST_OK ? "TLS_ST_OK":"error", "TLS_ST_OK");
            connected = 1;
            break;
        }
        get_handle_message_f(conn->ssl, &handle); 
        conn->ssl->pkt_size += handle(conn->ssl, position);
        if (conn->ssl->hand_state == TLS_ST_CR_SIGN) {
            conn->ssl->pkt_size = 0;
        }

        if (conn->ssl->hand_state == TLS_ST_SR_KEY_SHARE) {
            conn->ssl->pkt_size = 0;
        }

        position = &conn->buf[conn->ssl->pkt_size];

        if (conn->ssl->hand_state == TLS_ST_SW_SIGN) {
            ret_size = ksock_send(client_sock, conn->buf, conn->ssl->pkt_size);
            printk("ksock_send server_hello: %d bytes \n", ret_size);
            ret_size = ksock_recv(client_sock, conn->buf, BUFFER_SIZE, MSG_NOSIGNAL);
            printk("ksock_recv finshed: %d bytes \n", ret_size);
            print_hex_dump(KERN_CONT, "kernel_recv_client_finished:", DUMP_PREFIX_OFFSET, 16, 1, conn->buf, ret_size, false);
            if (ret_size < 0) {
                goto end;
            }
            position = &conn->buf[0];
            conn->ssl->pkt_size = 0;
        }

        if (conn->ssl->hand_state == TLS_ST_CW_SIGN) {
            int ret_size2 = do_statem_write(conn, conn->ssl->pkt_size);
            printk("client: ksock_send finish %d bytes\n", ret_size2);
            if (ret_size2 < 0) {
                goto end;
            }
        }

        if (conn->ssl->hand_state == TLS_ST_CW_KEY_SHARE) {
            ret_size = do_statem_write(conn, conn->ssl->pkt_size);
            printk("hand_state:%d connected:%d\n", conn->ssl->hand_state, connected);
            printk("client: ksock_send client_hello %d bytes\n", ret_size);
            ret_size = do_statem_read(conn, BUFFER_SIZE, MSG_NOSIGNAL);
            if (ret_size <= BUFFER_SIZE && ret_size > 0) {
                print_hex_dump(KERN_CONT, "kernel_recv_serverhello:", DUMP_PREFIX_OFFSET, 16, 1, conn->buf, ret_size, false);
            } else {
                printk("recv_serverhello error :%d bytes", ret_size);
                goto end;
            }
            conn->ssl->pkt_size = 0;
        } 
    }

    if (server) {
        printk("release socket now\n");
        if (client_sock != NULL)
            sock_release(client_sock);
        goto server_accept;
    }

end:
    if (server) {
        if (client_sock != NULL)
            sock_release(client_sock);
        if (conn->sock != NULL)
            sock_release(conn->sock);
    }
    if (conn != NULL) {
        free_connection(conn);
    }

    return 0;
}

int ssl_statem_client_transition(SSL_CONNECTION *s)
{
    switch (s->hand_state) {

        case TLS_ST_BEFORE:
            s->hand_state = TLS_ST_CW_CLNT_HELLO;
            break;

        case TLS_ST_CW_CLNT_HELLO:
                s->hand_state = TLS_ST_CW_SUBJECT;
            break;

        case TLS_ST_CW_SUBJECT:
                s->hand_state = TLS_ST_CW_KEY_SHARE;
            break;

        case TLS_ST_CW_KEY_SHARE:
                s->hand_state = TLS_ST_CR_SRVR_HELLO;
            break;

        case TLS_ST_CW_SUBJECT:
            s->hand_state = TLS_ST_CW_SIGN;
            break;

        case TLS_ST_CR_SRVR_HELLO:
            s->hand_state = TLS_ST_CR_KEY_SHARE;
            break;

        case TLS_ST_CR_KEY_SHARE:
            if (connected) {
                s->hand_state = TLS_ST_CR_SUBJECT;
            } else {
                s->hand_state = TLS_ST_CR_CERT;
            }
            break;

        case TLS_ST_CR_SUBJECT:
        case TLS_ST_CR_CERT:
            s->hand_state = TLS_ST_CR_FINISHED;
            break;

        case TLS_ST_CR_FINISHED:
            s->hand_state = TLS_ST_CR_SIGN;
            break;

        case TLS_ST_CR_SIGN:
            s->hand_state = TLS_ST_CW_CERT;
            break;

        case TLS_ST_CW_CERT:
            s->hand_state = TLS_ST_CW_FINISHED;
            break;

        case TLS_ST_CW_FINISHED:
            s->hand_state = TLS_ST_CW_SIGN;
            break;

        case TLS_ST_CW_SIGN:
            s->hand_state = TLS_ST_OK;
            break;
    }
    return -1;
}

int ssl_statem_server_transition(SSL_CONNECTION *s)
{
    switch (s->hand_state) {

        case TLS_ST_BEFORE:
            s->hand_state = TLS_ST_SR_CLNT_HELLO;
            break;

        case TLS_ST_SR_CLNT_HELLO:
            s->hand_state = TLS_ST_SR_SUBJECT;
            break;

        case TLS_ST_SR_SUBJECT:
            s->hand_state = TLS_ST_SR_KEY_SHARE;
            break;

        case TLS_ST_SR_KEY_SHARE:
            s->hand_state = TLS_ST_SW_SRVR_HELLO;
            break;

        case TLS_ST_SW_SRVR_HELLO:
            s->hand_state = TLS_ST_SW_KEY_SHARE;
            break;

        case TLS_ST_SW_KEY_SHARE:
            if (connected) {
                s->hand_state = TLS_ST_SW_SUBJECT;
            } else {
                s->hand_state = TLS_ST_SW_CERT;
            }
            break;

        case TLS_ST_SW_SUBJECT:
        case TLS_ST_SW_CERT:
            s->hand_state = TLS_ST_SW_FINISHED;
            break;

        case TLS_ST_SW_FINISHED:
            s->hand_state = TLS_ST_SW_SIGN;
            break;

        case TLS_ST_SW_SIGN:
            s->hand_state = TLS_ST_SR_CERT;
            break;

        case TLS_ST_SR_CERT:
            s->hand_state = TLS_ST_SR_FINISHED;
            break;

        case TLS_ST_SR_FINISHED:
            s->hand_state = TLS_ST_SR_SIGN;
            break;
        case TLS_ST_SR_SIGN:
            s->hand_state = TLS_ST_OK;
            break;

    }
    return -1;
}
int ssl_statem_client_handle_message(SSL_CONNECTION *s,
                                     handlefunc_f *confunc)
{
    switch (s->hand_state) {
        default:
            break;
        case TLS_ST_CW_CLNT_HELLO:
            *confunc = tls_construct_client_hello;
            break;
        case TLS_ST_CW_KEY_SHARE:
            *confunc = tls_construct_ctos_key_share;
            break;
        case TLS_ST_CW_CERT:
            *confunc = tls_construct_client_certificate;
            break;
        case TLS_ST_CW_SUBJECT:
            *confunc = tls_construct_client_subject;
            break;
        case TLS_ST_CW_SIGN:
            *confunc = tls_construct_client_signature;
            break;
        case TLS_ST_CR_SRVR_HELLO:
            *confunc = tls_process_server_hello;
            break;
        case TLS_ST_CR_KEY_SHARE:
            *confunc = tls_process_stoc_key_share;
            break;
        case TLS_ST_CR_CERT:
            *confunc = tls_process_server_certificate;
            break;
        case TLS_ST_CR_SUBJECT:
            *confunc = tls_process_server_subject;
            break;
        case TLS_ST_CR_FINISHED:
            *confunc = tls_process_finished;
            break;
        case TLS_ST_CR_SIGN:
            *confunc = tls_process_server_signature;
            break;
        case TLS_ST_CW_FINISHED:
            *confunc = tls_construct_finished;
            break;
    }

    return 1;
}

int ssl_statem_server_handle_message(SSL_CONNECTION *s,
                                     handlefunc_f *confunc)
{
    switch (s->hand_state) {
        default:
            return 0;
        case TLS_ST_SR_CLNT_HELLO:
            *confunc = tls_process_client_hello;
            break;
        case TLS_ST_SR_KEY_SHARE:
            *confunc = tls_process_ctos_key_share;
            break;
        case TLS_ST_SR_CERT:
            *confunc = tls_process_client_certificate;
            break;
        case TLS_ST_SR_SUBJECT:
            *confunc = tls_process_client_subject;
            break;
        case TLS_ST_SR_SIGN:
            *confunc = tls_process_client_signature;
            break;
        case TLS_ST_SW_SRVR_HELLO:
            *confunc = tls_construct_server_hello;
            break;
        case TLS_ST_SW_KEY_SHARE:
            *confunc = tls_construct_stoc_key_share;
            break;
        case TLS_ST_SW_CERT:
            *confunc = tls_construct_server_certificate;
            break;
        case TLS_ST_SW_SUBJECT:
            *confunc = tls_construct_server_subject;
            break;
        case TLS_ST_SW_FINISHED:
            *confunc = tls_construct_finished;
            break;
        case TLS_ST_SW_SIGN:
            *confunc = tls_construct_server_signature;
            break;
        case TLS_ST_SR_FINISHED:
            *confunc = tls_process_finished;
            break;
    }

    return 1;
}
int tls_construct_client_hello(SSL_CONNECTION *s, PACKET *pkt) {
    RECORD_LAYER *rr = (RECORD_LAYER *)pkt;
    SUB_RECORD_LAYER *sl = (SUB_RECORD_LAYER *)(pkt + sizeof(RECORD_LAYER));
    rr->type = SSL3_RT_HANDSHAKE;
    rr->version = htons(TLS1_VERSION);
    rr->length = 0x01 + (0x26 << 8);
    sl->type = 0x01;
    sl->length = 0x4 + (0x4 << 8);
    sl->version = TLS1_2_VERSION;
    get_random_bytes(&sl->random, sizeof(sl->random));
    print_hex_dump(KERN_CONT, "client_random:", DUMP_PREFIX_OFFSET, 16, 1, &sl->random, sizeof(sl->random), false);
    return CLIENT_HELLO_PKT_SIZE;
}

int tls_construct_server_hello(SSL_CONNECTION *s, PACKET *pkt) {
    RECORD_LAYER *rr = (RECORD_LAYER *)pkt;
    SUB_RECORD_LAYER *sl = (SUB_RECORD_LAYER *)(pkt + sizeof(RECORD_LAYER));
    rr->type = SSL3_RT_HANDSHAKE;
    rr->version = htons(TLS1_VERSION);
    rr->length = 0x01 + (0x26 << 8);
    sl->type = 0x02;
    sl->length = 0x5 + (0x5 << 8);
    sl->version = TLS1_2_VERSION;
    get_random_bytes(&sl->random, sizeof(sl->random));
    print_hex_dump(KERN_CONT, "server_random:", DUMP_PREFIX_OFFSET, 16, 1, &sl->random, sizeof(sl->random), false);
    return SERVER_HELLO_PKT_SIZE;
}

int tls_process_client_hello(SSL_CONNECTION *s, PACKET *pkt) {
    // TODO: check header

    return CLIENT_HELLO_PKT_SIZE;
}

int tls_process_server_hello(SSL_CONNECTION *s, PACKET *pkt) {
    // TODO: check header
    return SERVER_HELLO_PKT_SIZE;
}

int tls_construct_client_certificate(SSL_CONNECTION *s, PACKET *pkt) {
    RECORD_LAYER *rr = (RECORD_LAYER *)pkt;
    CERT_SUB_RECORD_LAYER *sl = (CERT_SUB_RECORD_LAYER *)(pkt + sizeof(RECORD_LAYER));
    int cert_length;
    rr->type = SSL3_RT_HANDSHAKE;
    rr->version = TLS1_2_VERSION;
    rr->length = 0x01 + (0x26 << 8);
    sl->type = 0x0b;
    sl->length = 0x4 + (0x4 << 8);
    cert_length = kread_cert(pkt + CLIENT_HELLO_CERT_HEADER, CLIENT_CERT_PATH);
    sl->cert_length = htons(cert_length);
    return CLIENT_HELLO_CERT_HEADER + cert_length;
}

int tls_construct_server_certificate(SSL_CONNECTION *s, PACKET *pkt) {
    RECORD_LAYER *rr = (RECORD_LAYER *)pkt;
    CERT_SUB_RECORD_LAYER *sl = (CERT_SUB_RECORD_LAYER *)(pkt + sizeof(RECORD_LAYER));
    int cert_length;
    rr->type = SSL3_RT_HANDSHAKE;
    rr->version = TLS1_2_VERSION;
    rr->length = 0x01 + (0x26 << 8);
    sl->type = 0x0b;
    sl->length = 0x4 + (0x4 << 8);
    cert_length = kread_cert(pkt + SERVER_HELLO_CERT_HEADER, SERVER_CERT_PATH);
    sl->cert_length = htons(cert_length);
    return SERVER_HELLO_CERT_HEADER + cert_length;
}

int tls_process_client_certificate(SSL_CONNECTION *s, PACKET *pkt) {
    CERT_SUB_RECORD_LAYER *sl = (CERT_SUB_RECORD_LAYER *)(pkt + sizeof(RECORD_LAYER));
    const void *cert = pkt + sizeof(RECORD_LAYER) + sizeof(CERT_SUB_RECORD_LAYER);
    int cert_length = 0;
    cert_length = ntohs(sl->cert_length);
    printk("server recv client cert size:%d\n", cert_length);
    // print_hex_dump(KERN_CONT, "kcert_parse:", DUMP_PREFIX_OFFSET, 16, 1, pkt, 100, false);
    if (kcert_parse(cert, client_pubkey, cert_length, s) < 0) {
        printk("kcert_parse error!\n");
    }
    return CLIENT_HELLO_CERT_HEADER + cert_length;
}

int tls_process_server_certificate(SSL_CONNECTION *s, PACKET *pkt) {
    CERT_SUB_RECORD_LAYER *sl = (CERT_SUB_RECORD_LAYER *)(pkt + sizeof(RECORD_LAYER));
    const void *cert = pkt + sizeof(RECORD_LAYER) + sizeof(CERT_SUB_RECORD_LAYER);
    int cert_length = 0;
    cert_length = ntohs(sl->cert_length);
    printk("client recv cert size:%d\n", cert_length);
    // print_hex_dump(KERN_CONT, "kcert_parse:", DUMP_PREFIX_OFFSET, 16, 1, cert, cert_length, false);
    if (kcert_parse(cert, server_pubkey, cert_length, s) < 0) {
        printk("kcert_parse error!\n");
    }
    return SERVER_HELLO_CERT_HEADER + cert_length;
}

int tls_construct_client_subject(SSL_CONNECTION *s, PACKET *pkt) {
    RECORD_LAYER *rr = (RECORD_LAYER *)pkt;
    unsigned char *pos = pkt + sizeof(RECORD_LAYER);
    const char *subject = "Internet Widgits Pty Ltd";
    int subject_length = strlen(subject);
    rr->type = SSL3_RT_HANDSHAKE;
    rr->version = htons(TLS1_2_VERSION);
    rr->length = htons(subject_length);
    memcpy(pos, subject, subject_length);
    return sizeof(RECORD_LAYER) + subject_length;
}

int tls_construct_server_subject(SSL_CONNECTION *s, PACKET *pkt) {
    RECORD_LAYER *rr = (RECORD_LAYER *)pkt;
    unsigned char *pos = pkt + sizeof(RECORD_LAYER);
    const char *subject = "Internet Widgits Pty Ltd";
    int subject_length = strlen(subject);
    rr->type = SSL3_RT_HANDSHAKE;
    rr->version = htons(TLS1_2_VERSION);
    rr->length = htons(subject_length);
    memcpy(pos, subject, subject_length);
    return sizeof(RECORD_LAYER) + subject_length;
}

int tls_process_client_subject(SSL_CONNECTION *s, PACKET *pkt) {
    RECORD_LAYER *rr = (RECORD_LAYER *)pkt;
    return sizeof(RECORD_LAYER) + rr->length;
}

int tls_process_server_subject(SSL_CONNECTION *s, PACKET *pkt) {
    RECORD_LAYER *rr = (RECORD_LAYER *)pkt;
    return sizeof(RECORD_LAYER) + rr->length;
}

int tls_construct_ctos_key_share(SSL_CONNECTION *s, PACKET *pkt) {
    KEY_SHARE_LAYER *kl = (KEY_SHARE_LAYER *)pkt; 
    kl->group_id = htons(0x1d);
    kl->length = htons(0x20);
    ssl_generate_pkey(s);
    ssl_generate_pubkey(s);
    memcpy(kl->keyshare, s->pubkey, 32);
    print_hex_dump(KERN_CONT, "client keyshare:", DUMP_PREFIX_OFFSET, 16, 1, s->pubkey, 32, false);
    return KEY_SHARE_PKT_SIZE;
}

int tls_construct_stoc_key_share(SSL_CONNECTION *s, PACKET *pkt) {
    KEY_SHARE_LAYER *kl = (KEY_SHARE_LAYER *)pkt; 
    kl->group_id = htons(0x1d);
    kl->length = htons(0x20);
    ssl_generate_pkey(s);
    ssl_generate_pubkey(s);
    memcpy(kl->keyshare, s->pubkey, 32);
    print_hex_dump(KERN_CONT, "server keyshare:", DUMP_PREFIX_OFFSET, 16, 1, s->pubkey, 32, false);
    ssl_generate_pms(s);
    memcpy(server_pms, s->pms, 32);
    print_hex_dump(KERN_CONT, "server gen pms:", DUMP_PREFIX_OFFSET, 16, 1, s->pms, 32, false);
    return KEY_SHARE_PKT_SIZE;
}

int tls_process_ctos_key_share(SSL_CONNECTION *s, PACKET *pkt) {
    KEY_SHARE_LAYER *kl = (KEY_SHARE_LAYER *)pkt; 
    memcpy(s->peer_pubkey, kl->keyshare, 32);
    return KEY_SHARE_PKT_SIZE;
}

int tls_process_stoc_key_share(SSL_CONNECTION *s, PACKET *pkt) {
    KEY_SHARE_LAYER *kl = (KEY_SHARE_LAYER *)pkt; 
    memcpy(s->peer_pubkey, kl->keyshare, 32);
    ssl_generate_pms(s);
    print_hex_dump(KERN_CONT, "client gen pms:", DUMP_PREFIX_OFFSET, 16, 1, s->pms, 32, false);
    memcpy(client_pms, s->pms, 32);
    return KEY_SHARE_PKT_SIZE;
}

unsigned char RSA_OID[] = {0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, 0x01, 0x01};

int tls_construct_client_signature(SSL_CONNECTION *s, PACKET *pkt) {
    RECORD_LAYER *rr = (RECORD_LAYER *)pkt;
    void *key = NULL;
    PACKET in[32];
    int signlen;
    rr->type = SSL3_RT_HANDSHAKE;
    rr->version = TLS1_2_VERSION;
    rr->length = 0x01 + (0x01 << 8);
    sha256(pkt - s->pkt_size, s->pkt_size, in);
    key = kzalloc(4096, GFP_KERNEL);
    int keylen = kread_key(key, SERVER_KEY_PATH);
    if (keylen < 0) return -1;
    if(!strncmp((char *)key + 9, RSA_OID, sizeof(RSA_OID))) {
        pkcs1pad_sign(key, in, 32, pkt + sizeof(RECORD_LAYER), 512);
        signlen = 512;
    } else {
        const struct uECC_Curve_t *curves;
        curves = uECC_secp256r1();
        uECC_sign((char *)key + 36, in, 32, pkt + sizeof(RECORD_LAYER), curves);
        signlen = 64;
    }
    return signlen + sizeof(RECORD_LAYER);
}

int tls_construct_server_signature(SSL_CONNECTION *s, PACKET *pkt) {
    RECORD_LAYER *rr = (RECORD_LAYER *)pkt;
    void *key = NULL;
    PACKET in[32];
    int signlen;
    rr->type = SSL3_RT_HANDSHAKE;
    rr->version = TLS1_2_VERSION;
    rr->length = 0x01 + (0x01 << 8);
    sha256(pkt - s->pkt_size, s->pkt_size, in);
    key = kzalloc(4096, GFP_KERNEL);
    int keylen = kread_key(key, SERVER_KEY_PATH);
    if (keylen < 0) return -1;
    if(!strncmp((char *)key + 9, RSA_OID, sizeof(RSA_OID))) {
        pkcs1pad_sign(key, in, 32, pkt + sizeof(RECORD_LAYER), 512);
        signlen = 512;
    } else {
        printk("enter ecdsa sig ============\n");
        const struct uECC_Curve_t *curves;
        curves = uECC_secp256r1();
        uECC_sign((char *)key + 36, in, 32, pkt + sizeof(RECORD_LAYER), curves);
        signlen = 64;
    }
    return signlen + sizeof(RECORD_LAYER);
}

int tls_process_client_signature(SSL_CONNECTION *s, PACKET *pkt) {
    unsigned char hash_result[32];
    int siglen;
    sha256(pkt - s->pkt_size, s->pkt_size, hash_result);
    
    printk("pkt_size:%d\n", s->pkt_size);

    if (s->cert_type == TYPE_RSA) {
        pkcs1pad_verify(client_pubkey, hash_result, 32, pkt + sizeof(RECORD_LAYER), 512);
        siglen = 512;
    } else {
        siglen = 64;
        const struct uECC_Curve_t *curves;
        curves = uECC_secp256r1();
        if (!uECC_verify(client_pubkey + 1, hash_result, 32, pkt + sizeof(RECORD_LAYER), curves)) {
            printk("ecdsa verify failed\n");
        } else {
            printk("ecdsa verfiy success!\n");
        }
    }
    return siglen + sizeof(RECORD_LAYER);
}

int tls_process_server_signature(SSL_CONNECTION *s, PACKET *pkt) {
    unsigned char hash_result[32];
    sha256(pkt - s->pkt_size, s->pkt_size, hash_result);
    print_hex_dump(KERN_CONT, "client sha256:", DUMP_PREFIX_OFFSET, 16, 1, hash_result, 32, false);
    int signlen;
    
    if (s->cert_type == TYPE_RSA) {
        pkcs1pad_verify(server_pubkey, hash_result, 32, pkt + sizeof(RECORD_LAYER), 512);
        signlen = 512;
    } else {
        const struct uECC_Curve_t *curves;
        curves = uECC_secp256r1();
        signlen = 64;
    // print_hex_dump(KERN_CONT, "server_pubkey:", DUMP_PREFIX_OFFSET, 16, 1, server_pubkey, , false);
        if (!uECC_verify(server_pubkey + 1, hash_result, 32, pkt + sizeof(RECORD_LAYER), curves)) {
            printk("ecdsa verify failed\n");
        } else {
            printk("ecdsa verfiy success!\n");
        }
    }
    return signlen + sizeof(RECORD_LAYER);
}

int tls_construct_finished(SSL_CONNECTION *s, PACKET *pkt) {
    RECORD_LAYER *rr = (RECORD_LAYER *)pkt;
    int *p;
    unsigned char output[32];
    rr->type = SSL3_RT_HANDSHAKE;
    rr->version = TLS1_2_VERSION;
    p = (int *)(pkt + sizeof(RECORD_LAYER));
    *p = 0x0e;
    p += 1;
    if (s->server) {
        rr->length = htons(0x04);
        return sizeof(RECORD_LAYER) + 4;
    } else {
        rr->length = htons(0x24);
        hmac_sha256(client_pms, 32, "connection_id", 13, output);
        memcpy(p, output, 32);
        return sizeof(RECORD_LAYER) + 4 + 32;
    }
}

int tls_process_finished(SSL_CONNECTION *s, PACKET *pkt) {
    if (s->server) {
        unsigned char output[32];
        hmac_sha256(server_pms, 32, "connection_id", 13, output);
        print_hex_dump(KERN_CONT, "server verify hmac:", DUMP_PREFIX_OFFSET, 16, 1, output, 32, false);
        return sizeof(RECORD_LAYER) + 4 + 32;
    } else {
        return sizeof(RECORD_LAYER) + 4;
    }
}
